#include "simple_logger.h"
#include <mutex>
#include <string>
#include <cstring>
#include <sstream>
#include "log4cplus/logger.h"
#include "log4cplus/consoleappender.h"
#include "log4cplus/fileappender.h"
#include "log4cplus/layout.h"
#include "log4cplus/helpers/loglog.h"

using namespace log4cplus;
using namespace log4cplus::helpers;
using namespace std;

SimpleLogger *SimpleLogger::Get()
{
    static SimpleLogger logger;
    return &logger;
}

Logger &SimpleLogger::LoggerRef()
{
    return logger;
}

void SimpleLogger::Init(LEVEL lvl, const char *dir, const char *pattern)
{
    static bool is_first = true;
    if (is_first)
    {
        mtx_.lock();
        if (is_first)
        {
            stringstream ss;
            SharedObjectPtr<Appender> console_append(new ConsoleAppender());
            console_append->setName("console");
            ss << dir << "total.log";
            SharedObjectPtr<Appender> file_append(new FileAppender(ss.str(), ios::app, true));
            file_append->setName("file");
            ss.clear();
            ss.str("");
            ss << dir << "daily.log";
            SharedObjectPtr<Appender> daily_append(new DailyRollingFileAppender(ss.str(), WEEKLY, 5 * 1024 * 1024, 10, true));
            daily_append->setName("daily");
            auto_ptr<Layout> layout1(new PatternLayout(pattern));
            auto_ptr<Layout> layout2(new PatternLayout(pattern));
            auto_ptr<Layout> layout3(new PatternLayout(pattern));
            console_append->setLayout(layout1);
            file_append->setLayout(layout2);
            daily_append->setLayout(layout3);
            logger = Logger::getInstance("sms_security");
            logger.addAppender(console_append);
            logger.addAppender(file_append);
            logger.addAppender(daily_append);
            switch (lvl)
            {
            case DEBUG:
                logger.setLogLevel(DEBUG_LOG_LEVEL);
                break;
            case INFO:
                logger.setLogLevel(INFO_LOG_LEVEL);
                break;
            case WARN:
                logger.setLogLevel(WARN_LOG_LEVEL);
                break;
            case ERROR:
                logger.setLogLevel(ERROR_LOG_LEVEL);
                break;
            default:
                logger.setLogLevel(ALL_LOG_LEVEL);
            }
            is_first = false;
        }
        mtx_.unlock();
    }
}

void SimpleLogger::Init(string lvl, string dir, string pattern)
{
    LEVEL level = ALL;
    if (strcmp(lvl.c_str(), "DEBUG") == 0)
    {
        level = DEBUG;
    }
    if (strcmp(lvl.c_str(), "INFO") == 0)
    {
        level = INFO;
    }
    if (strcmp(lvl.c_str(), "WARN") == 0)
    {
        level = WARN;
    }
    if (strcmp(lvl.c_str(), "ERROR") == 0)
    {
        level = ERROR;
    }
    this->Init(level, dir.c_str(), pattern.c_str());
}